﻿using System;
using System.Threading.Tasks;
using Coding4Fun.Maelstrom.Common;
using Windows.Foundation;
using Windows.Storage.Streams;

namespace Coding4Fun.Maelstrom.Communication
{
	public sealed class GameStatePacket: IGamePacket
	{
		public PacketType Type { get { return PacketType.GameStatePacket; } }

		public GameState GameState { get; set; }
		public Point3 Puck1Position { get; set; }
		public Point3 Puck2Position { get; set; }
		public Point3 Puck3Position { get; set; }
		public bool Puck1Active { get; set; }
		public bool Puck2Active { get; set; }
		public bool Puck3Active { get; set; }
		public Point3 Paddle1NormalizedPosition { get; set; }
		public Point3 Paddle2NormalizedPosition { get; set; }
		public int Player1Score { get; set; }
		public int Player2Score { get; set; }

		public int SplitSegment1 { get; set; }
		public int SplitSegment2 { get; set; }
		public int SplitSegment3 { get; set; }
		public int SplitSegment4 { get; set; }

		public IAsyncAction FromDataReaderAsync(DataReader reader)
		{
			return FromDataReaderAsyncInternal(reader).AsAsyncAction();
		}

		private async Task FromDataReaderAsyncInternal(DataReader reader)
		{
			await reader.LoadAsync(sizeof(Int32));
			GameState = (GameState)reader.ReadInt32();

			Puck1Position = new Point3();
			await reader.LoadAsync(sizeof(double) * 3);
			Puck1Position.X = (float)reader.ReadDouble();
			Puck1Position.Y = (float)reader.ReadDouble();
			Puck1Position.Z = (float)reader.ReadDouble();

			Puck2Position = new Point3();
			await reader.LoadAsync(sizeof(double) * 3);
			Puck2Position.X = (float)reader.ReadDouble();
			Puck2Position.Y = (float)reader.ReadDouble();
			Puck2Position.Z = (float)reader.ReadDouble();

			Puck3Position = new Point3();
			await reader.LoadAsync(sizeof(double) * 3);
			Puck3Position.X = (float)reader.ReadDouble();
			Puck3Position.Y = (float)reader.ReadDouble();
			Puck3Position.Z = (float)reader.ReadDouble();

			await reader.LoadAsync(sizeof(bool) * 3);
			Puck1Active = reader.ReadBoolean();
			Puck2Active = reader.ReadBoolean();
			Puck3Active = reader.ReadBoolean();

			Paddle1NormalizedPosition = new Point3();
			await reader.LoadAsync(sizeof(double) * 3);
			Paddle1NormalizedPosition.X = (float)reader.ReadDouble();
			Paddle1NormalizedPosition.Y = (float)reader.ReadDouble();
			Paddle1NormalizedPosition.Z = (float)reader.ReadDouble();

			Paddle2NormalizedPosition = new Point3();
			await reader.LoadAsync(sizeof(double) * 3);
			Paddle2NormalizedPosition.X = (float)reader.ReadDouble();
			Paddle2NormalizedPosition.Y = (float)reader.ReadDouble();
			Paddle2NormalizedPosition.Z = (float)reader.ReadDouble();

			await reader.LoadAsync(sizeof(int) * 2);
			Player1Score = reader.ReadInt32();
			Player2Score = reader.ReadInt32();

			await reader.LoadAsync(sizeof(int) * 4);
			SplitSegment1 = reader.ReadInt32();
			SplitSegment2 = reader.ReadInt32();
			SplitSegment3 = reader.ReadInt32();
			SplitSegment4 = reader.ReadInt32();
		}

		public void WritePacket(DataWriter writer)
		{
			writer.WriteInt32((int)GameState);

			writer.WriteDouble(Puck1Position.X);
			writer.WriteDouble(Puck1Position.Y);
			writer.WriteDouble(Puck1Position.Z);

			writer.WriteDouble(Puck2Position.X);
			writer.WriteDouble(Puck2Position.Y);
			writer.WriteDouble(Puck2Position.Z);

			writer.WriteDouble(Puck3Position.X);
			writer.WriteDouble(Puck3Position.Y);
			writer.WriteDouble(Puck3Position.Z);

			writer.WriteBoolean(Puck1Active);
			writer.WriteBoolean(Puck2Active);
			writer.WriteBoolean(Puck3Active);

			writer.WriteDouble(Paddle1NormalizedPosition.X);
			writer.WriteDouble(Paddle1NormalizedPosition.Y);
			writer.WriteDouble(Paddle1NormalizedPosition.Z);

			writer.WriteDouble(Paddle2NormalizedPosition.X);
			writer.WriteDouble(Paddle2NormalizedPosition.Y);
			writer.WriteDouble(Paddle2NormalizedPosition.Z);

			writer.WriteInt32(Player1Score);
			writer.WriteInt32(Player2Score);

			writer.WriteInt32(SplitSegment1);
			writer.WriteInt32(SplitSegment2);
			writer.WriteInt32(SplitSegment3);
			writer.WriteInt32(SplitSegment4);
		}
	}
}
